/*
 * Copyright (c) 2011 Salzburg Research.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package at.newmedialab.skwrl.api;

import at.newmedialab.skwrl.model.Justification;

import java.net.URI;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;

/**
 * A generic API for RDF models and triple stores. Implementations exist for Sesame, LMF, Jena and
 * Clerezza. The API is somewhat typesafe by making use of a generic for nodes.
 * <p/>
 * Needs to provide the following functionalities:
 * <ul>
 *     <li>notification of the reasoning engine of updates in the triple store via a listener</li>
 *     <li>management of RDF resources and literals (creation and retrieval)</li>
 *     <li>management of RDF triples (creation and listing); preferrably, the system has a means
 *         to distinguish between inferred and base triples</li>
 *     <li>management and storage of justifications for inferred triples (adding, removing, querying)</li>
 * </ul>
 * <p/>
 * Author: Sebastian Schaffert
 */
public interface SKWRLBackend<Triple,Node> {

    /**
     * Register a TripleUpdateListener. The listener should be called whenever a triple update in the underlying
     * RDF backend occurs. The backend may decide to bundle updates into a transaction.
     *
     * @param listener the listener to register
     */
    public void addTripleUpdateListener(TripleUpdateListener<Triple> listener);


    public void removeTripleUpdateListener(TripleUpdateListener<Triple> listener);


    /**
     * Test whether the node passed as argument is a literal
     * @param n the node to check
     * @return true if the node is a literal
     */
    public boolean isLiteral(Node n);

    /**
     * Test whether the node passed as argument is a URI
     * @param n the node to check
     * @return true if the node is a URI
     */
    public boolean isURI(Node n);

    /**
     * Test whether the node passed as argument is a blank node
     * @param n the node to check
     * @return true if the node is a blank node
     */
    public boolean isBlank(Node n);


    /**
     * Return the string value of a node. For a literal, this will be the content, for a URI node it will be the
     * URI itself, and for a blank node it will be the identifier of the node.
     * @param node
     * @return
     */
    public String stringValue(Node node);


    /**
     * Create a literal node with the content passed as argument
     * @param content  string content to represent inside the literal
     * @return a literal node in using the model used by this backend
     */
    public Node createLiteral(String content);

    /**
     * Create a literal node with the content passed as argument
     * @param content  string content to represent inside the literal
     * @return a literal node in using the model used by this backend
     */
    public Node createLiteral(String content, Locale language, URI type);

    /**
     * Create a URI mode with the URI passed as argument
     * @param uri  URI of the resource to create
     * @return a URI node using the model used by this backend
     */
    public Node createURI(String uri);

    /**
     * Return the subject of the triple passed as argument.
     *
     * @param triple the triple for which to return the subject
     * @return the node representing the subject of the triple
     */
    public Node getSubject(Triple triple);

    /**
     * Return the property of the triple passed as argument.
     *
     * @param triple the triple for which to return the property
     * @return the node representing the property of the triple
     */
    public Node getProperty(Triple triple);

    /**
     * Return the object of the triple passed as argument.
     *
     * @param triple the triple for which to return the object
     * @return the node representing the object of the triple
     */
    public Node getObject(Triple triple);


    /**
     * List the triples matching a given pattern of subject, property, object and context.
     * Null values are treated as wildcards, i.e. match any value. The returned iterable
     * should be implemented in a memory-efficient way if possible, retrieving
     * subsequent triples only when requested.
     *
     * @param subject   a node identifying the subject the returned triples should have
     * @param property  a node identifying the property the returned triples should have
     * @param object    a node identifying the object the returned triples should have
     * @param context   a node identifying the context the returned triples should have
     * @return an iterable allowing to list the triples matching the query criteria
     */
    public Iterable<Triple> listTriples(Node subject, Node property, Node object, Node context);

    /**
     * List all inferred triples stored in the backend.
     * @return
     */
    public Iterable<Triple> listInferredTriples();

    /**
     * Remove all inferred triples stored in the backend.
     */
    public void removeInferredTriples();





    /**
     * List all justifications stored in the system.
     * @return
     */
    public Set<Justification<Triple>> listJustifications();

    /**
     * Remove all justifications currently stored by the backend.
     */
    public void clearJustifications();

    /**
     * Add new justifications. The underlying backend should support
     * some means of persistently storing the justifications. This method
     * allows more efficient transactional addition of a collection of
     * justifications.
     *
     * @param justifications
     */
    public void addJustifications(Collection<Justification<Triple>> justifications);


    /**
     * Remove a collection of justification. The underlying backend should support
     * some means of persistently storing the justifications. This method
     * allows more efficient transactional addition of a collection of
     * justifications.
     *
     * @param justifications
     */
    public void removeJustifications(Collection<Justification<Triple>> justifications);
}
